#pragma once

#include "requestor.hpp"

using namespace std;

namespace Client
{
    class RpcCaller
    {
        public:
        using ptr=shared_ptr<RpcCaller>;
        using JsonAsyncResponse=std::future<Json::Value>;
        using JsonResponseCallBack=function<void(const Json::Value&)>;
        RpcCaller(const Requestor::ptr &requestor):_requestor(requestor){}

        //requestor中的回调函数是针对BaseMessage进行处理的
        //用户在RpcCaller中的回调函数是针对RpcResponse里面的result进行处理的
        bool Call(const BaseConnection::ptr&conn,const string &method,
                    const Json::Value&params, Json::Value &result)
        {
            std::string rid = UUID::uuid();
            DLog("开始rpc同步调用....:%s", rid.c_str());
            //1. 组织请求
            auto req_msg=MessageFactory::create<RpcRequest>();
            req_msg->SetId(rid);
            req_msg->SetMethod(method);
            req_msg->SetMtype(Mtype::REQ_RPC);
            req_msg->SetParams(params);
            BaseMessage::ptr rsp_msg;
            //2. 发送请求
            bool ret=_requestor->Send(conn,dynamic_pointer_cast<BaseMessage>(req_msg),rsp_msg);
            if(ret==false)
            {
                ELog("同步rpc请求失败！");
                return false;
            }
            DLog("收到响应，进行解析，获取结果！");
            //3. 等待响应
            auto rpc_rsp_msg=dynamic_pointer_cast<RpcResponse>(rsp_msg);
            if(!rpc_rsp_msg)
            {
                ELog("rpc响应，向下解析失败失败！");
                return false;
            }
            if(rpc_rsp_msg->GetRcode()!=RCode::RCODE_OK)
            {
                ELog("rpc请求出错！%s",ErrReason(rpc_rsp_msg->GetRcode()).c_str());
                return false;
            }
            DLog("结果设置完毕....");
            result=rpc_rsp_msg->GetResult();
            return true;
        }
        bool Call(const BaseConnection::ptr&conn,const string &method,
                 const Json::Value&params,   JsonAsyncResponse &result)
        {
            //向服务器发送异步回调请求，设置回调函数，回调函数中会传入一个promise对象，在回调函数中去堆promise设置数据
            auto req_msg=MessageFactory::create<RpcRequest>();
            req_msg->SetId(UUID::uuid());
            req_msg->SetMethod(method);
            req_msg->SetMtype(Mtype::REQ_RPC);
            req_msg->SetParams(params);
           
            auto json_promise=make_shared<promise<Json::Value>>();
            result=json_promise->get_future();
            Requestor::RequestCallback cb=bind(&RpcCaller::CallBack,this,json_promise,placeholders::_1);
            bool ret=_requestor->Send(conn,dynamic_pointer_cast<BaseMessage>(req_msg),cb);
            if(ret==false)
            {
                ELog("异步rpc请求失败！");
                return false;
            }
            return true;
        }
        bool Call(const BaseConnection::ptr&conn,const string &method,const Json::Value&params,
       const  JsonResponseCallBack &cb)
        {
            auto req_msg=MessageFactory::create<RpcRequest>();
            req_msg->SetId(UUID::uuid());
            req_msg->SetMethod(method);
            req_msg->SetMtype(Mtype::REQ_RPC);
            req_msg->SetParams(params);
           
            
            Requestor::RequestCallback req_cb=bind(&RpcCaller::CallBack1,this,cb,placeholders::_1);
            bool ret=_requestor->Send(conn,dynamic_pointer_cast<BaseMessage>(req_msg),req_cb);
            if(ret==false)
            {
                ELog("回调rpc请求失败！");
                return false;
            }
            return true;
        }
        private:
        void CallBack1(const JsonResponseCallBack&cb,const BaseMessage::ptr &msg)
        {
            auto rpc_rsp_msg=dynamic_pointer_cast<RpcResponse>(msg);
            if(!rpc_rsp_msg)
            {
                ELog("rpc响应，向下解析失败失败！");
                return ;
            }
            if(rpc_rsp_msg->GetRcode()!=RCode::RCODE_OK)
            {
                ELog("rpc回调请求出错！%s",ErrReason(rpc_rsp_msg->GetRcode()).c_str());
                return ;
            }
            cb(rpc_rsp_msg->GetResult());
        }
        void CallBack(shared_ptr<promise<Json::Value>> result,const BaseMessage::ptr &msg)
        {
            auto rpc_rsp_msg=dynamic_pointer_cast<RpcResponse>(msg);
            if(!rpc_rsp_msg)
            {
                ELog("rpc响应，向下解析失败失败！");
                return ;
            }
            if(rpc_rsp_msg->GetRcode()!=RCode::RCODE_OK)
            {
                ELog("rpc异步请求出错！%s",ErrReason(rpc_rsp_msg->GetRcode()).c_str());
                return ;
            }
           result->set_value(rpc_rsp_msg->GetResult());
        }
        private:
        Requestor::ptr _requestor;
    };
}

